#!/bin/bash

cleanup() {
    rm $f1
}

show_help() {
    echo -e "test gnocchi client"
    echo -e "Usage: $0 <instance uuid> <ALL|cpu|mem|net|disk|gpu|zabbix> [-f] [gnocchi options...]"
    echo -e "Example:"
    echo -e "$0 4b6c0529-2471-4f8c-be20-a455b0e7c792 cpu --granularity 300 --start \"2021-03-04T14:50:00+08:00\" --stop \"2021-03-04T15:55:00+08:00\""
    exit
}

measure_show(){
    local resid=$1
    local comment="$2"
    shift 2
    hint "$comment\n # gnocchi measures show $resid"
    gnocchi measures show $resid $*

}

get_metricid(){
    local listout=$1
    local metric=$2
    cat $listout|grep -w "$metric "|awk '{print $2}'
}

get_instresid(){
    local type=$1
    local instid=$2
    shift 2
    gnocchi resource search --type $type "instance_id=$instid" -f value $*|awk '{print $1}'
}

hint() {
    echo -e "\n\033[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\033[0m" >&1
    echo -e " $1" >&1
    echo -e "\033[31m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\033[0m" >&1
}

# now-600
parse_now() {
    if [ "${1:0:3}" == "now" ]; then
        echo "$(date --date @$(($(date +%s)${1:3})) +%Y-%m-%dT%H:%M:%S%:z)"
    else
        echo $1
    fi
}

if [ $# -eq 0 ]; then
    show_help
fi

op=$1
shift
force_update=false

if [ "$op" == "update" ]; then
    echo update metric list
else # op=="vm"
    mtype=ALL
    vmuuid=$1
    [ -n "$vmuuid" ] || { echo "no instance uuid found."; exit 2; }
    shift
    [ -n "$1" ] && { mtype=$1; shift; }
    [[ "$mtype" =~ ALL|cpu|mem|net|disk|gpu|zabbix ]] || { show_help; exit 1; }
fi

# parse "--granularity", "--start", "--stop" for "gnocchi measures show"
measureopts=
others=
# set positional parameters
eval set -- "$*"
cmdopts=$(getopt --longoptions \
granularity:,\
debug,\
start:,\
stop:,\
os-project-domain-name:,\
os-user-domain-name:,\
os-project-name:,\
os-username:,\
os-password:,\
os-auth-url:,\
os-interface:,\
os-region-name:,\
os-auth-type:,\
help \
                     --options +hf -- "$@")

granu=

while true; do
  case "$1" in
    -h | --help )
        show_help
        exit ;;
    -f )
        force_update=true
        shift;;
    --granularity )
        measureopts="$measureopts --granularity $2 "
        granu=$2
        shift 2;;
    --debug )
        measureopts="$measureopts --debug "
        shift;;
    --start )
        measureopts="$measureopts --start $(parse_now $2) "
        shift 2;;
    --stop )
        measureopts="$measureopts --stop $(parse_now $2) "
        shift 2;;
    --os-project-domain-name )
        others="$others --os-project-domain-name $2 "
        shift 2;;
    --os-user-domain-name )
        others="$others --os-user-domain-name $2 "
        shift 2;;
    --os-project-name )
        others="$others --os-project-name $2 "
        shift 2;;
    --os-username )
        others="$others --os-username $2 "
        shift 2;;
    --os-password )
        others="$others --os-password $2 "
        shift 2;;
    --os-auth-url )
        others="$others --os-auth-url $2 "
        shift 2;;
    --os-interface )
        others="$others --os-interface $2 "
        shift 2;;
    --os-region-name )
        others="$others --os-region-name $2 "
        shift 2;;
    --os-auth-type )
        others="$others --os-auth-type $2 "
        shift 2;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

##set -o xtrace

f0="/root/.gnocchi_metrics"
f1=$(mktemp)
[ -f "$f1" ] || exit -127
trap cleanup EXIT INT

if [[ "$op"  == "update" || ! -f "$f0" || "$force_update" == "true" ]]; then
    gnocchi metric list $others > $f0
fi
[ "$op" == "vm" ] || exit

cat $f0 |grep -w $vmuuid |tee $f1
cpu=$(get_metricid $f1 cpu)
[ -n "$cpu" ] || { echo "not found. try \"update\""; exit 2; }
if [[ "$mtype" == "ALL" || "$mtype" =~ "cpu" ]]; then
    measure_show $cpu "CPU时间（ns）" $others $measureopts
    hint "cpu利用率（%）"
    gnocchi aggregates $others $measureopts "(/ (aggregate rate:mean(metric cpu mean)) $((granu*10000000)))" id=$vmuuid $others
fi

memtotal=$(get_metricid $f1 memory)
memusage=$(get_metricid $f1 memory.usage)
if [[ "$mtype" == "ALL" || "$mtype" =~ "mem" ]]; then
    [ -n "$memtotal" ] && measure_show $memtotal "内存总量（MB）" $others $measureopts
    [ -n "$memusage" ] && measure_show $memusage "内存使用（MB）" $others $measureopts
elif [[ "$mtype" == "memtotal" ]]; then
    [ -n "$memtotal" ] && measure_show $memtotal "内存总量（MB）" $others $measureopts
fi


if [[ "$mtype" == "ALL" || "$mtype" =~ "net" ]]; then
    hint " # gnocchi resource search --type instance_network_interface \"instance_id=$vmuuid\""
    for netifres in $(get_instresid instance_network_interface $vmuuid $others); do
        hint " # gnocchi metric list |grep $netifres"
        cat $f0 |grep $netifres |tee $f1
        netinbytes=$(get_metricid $f1 network.incoming.bytes)
        netoutbytes=$(get_metricid $f1 network.outgoing.bytes)
        [ -n "$netinbytes" ] && measure_show $netinbytes "网络incoming流量（bytes）" $others $measureopts
        [ -n "$netoutbytes" ] && measure_show $netoutbytes "网络outgoing流量（bytes）" $others $measureopts
    done
fi

if [[ "$mtype" == "ALL" || "$mtype" =~ "disk" ]]; then
    hint " # gnocchi resource search --type instance_disk \"instance_id=$vmuuid\""
    for diskres in $(get_instresid instance_disk $vmuuid $others); do
        hint " # gnocchi metric list |grep $diskres"
        cat $f0 |grep $diskres |tee $f1
        wbytes=$(get_metricid $f1 disk.device.write.bytes)
        rbytes=$(get_metricid $f1 disk.device.read.bytes)
        [ -n "$wbytes" ] && measure_show $wbytes "磁盘写（bytes）" $others $measureopts
        [ -n "$rbytes" ] && measure_show $rbytes "磁盘读（bytes）" $others $measureopts
    done
fi

if [[ "$mtype" == "ALL" || "$mtype" =~ "gpu" ]]; then
    hint " # gnocchi resource search --type instance_nvidia \"instance_id=$vmuuid\""
    for gpures in $(get_instresid instance_nvidia $vmuuid $others); do
        hint " # gnocchi metric list |grep $gpures"
        cat $f0 |grep $gpures |tee $f1
        gpuutil=$(get_metricid $f1 nvidia.smi.gpu.util)
        memutil=$(get_metricid $f1 nvidia.smi.memory.util)
        [ -n "$gpuutil" ] && measure_show $gpuutil "GPU利用率（%）" $others $measureopts
        [ -n "$memutil" ] && measure_show $memutil "显存利用率（%s）" $others $measureopts
    done
fi

if [[ "$mtype" == "ALL" || "$mtype" =~ "zabbix" ]]; then
    hint " # gnocchi resource search --type instance_zabbix \"instance_id=$vmuuid\""
    for zabbixres in $(get_instresid instance_zabbix $vmuuid $others); do
        hint " # gnocchi metric list |grep $zabbixres"
        cat $f0 |grep $zabbixres |tee $f1
        cpuutil=$(get_metricid $f1 zabbix.stat.cpu.util)
        memused=$(get_metricid $f1 zabbix.stat.mem.used)
        diskread=$(get_metricid $f1 zabbix.stat.disk.read)
        diskwrite=$(get_metricid $f1 zabbix.stat.disk.write)
        netin=$(get_metricid $f1 zabbix.stat.net.in)
        netout=$(get_metricid $f1 zabbix.stat.net.out)
        [ -n "$cpuutil" ] && measure_show $cpuutil "CPU利用率（%）" $others $measureopts
        if [ -n "$memused" ]; then
#            measure_show $memused "内存使用（Bytes）" $others $measureopts
            hint "内存使用（Mbytes）\nGnocchi Operations: (/ (metric zabbix.stat.mem.used mean) 1048576)"
            gnocchi aggregates $others $measureopts "(/ (metric $memused mean) 1048576)" $others
           
        fi
        if [ -n "$diskread" ]; then
#            measure_show $diskread "磁盘读（Sectors/s）" $others $measureopts
            # XXX suppose 1 sector = 512 bytes
            hint "磁盘读速率（kbytes/s）\nGnocchi Operations: (/ (metric zabbix.stat.disk.read mean) 2)"
            gnocchi aggregates $others $measureopts "(/ (metric $diskread mean) 2)" $others
           
        fi
        if [ -n "$diskwrite" ]; then
#            measure_show $diskwrite "磁盘写（Sectors/s）" $others $measureopts
            # XXX suppose 1 sector = 512 bytes
            hint "磁盘写速率（kbytes/s）\nGnocchi Operations: (/ (metric zabbix.stat.disk.write mean) 2)"
            gnocchi aggregates $others $measureopts "(/ (metric $diskwrite mean) 2)" $others
        fi
        if [ -n "$netin" ]; then
#            measure_show $netin "网络入（Bytes）" $others $measureopts
            hint "网络incoming速率（kbytes/s）s）\nGnocchi Operations: (/ (aggregate rate:mean(metric zabbix.stat.net.in mean)) $((granu*1024)))"
            gnocchi aggregates $others $measureopts "(/ (aggregate rate:mean(metric $netin mean)) $((granu*1024)))" $others
        fi
        if [ -n "$netout" ]; then
#            measure_show $netout "网络出（Bytes）" $others $measureopts
            hint "网络outgoing速率（kbytes/s）\nGnocchi Operations: (/ (aggregate rate:mean(metric zabbix.stat.net.out mean)) $((granu*1024)))"
            gnocchi aggregates $others $measureopts "(/ (aggregate rate:mean(metric $netout mean)) $((granu*1024)))" $others
        fi
    done
fi

